import os
import pathlib
import typing
import shutil

from functools import partial
from enum import Enum




class SortKey(Enum):
    """文件排序的依据字段"""
    NAME = "name"          # 文件名（带后缀）
    STEM = "stem"          # 文件名（不带后缀）
    SIZE = "size"          # 文件大小
    MODIFIED_TIME = "mtime" # 修改时间
    CREATION_TIME = "ctime" # 创建时间 (Windows系统支持较好)

class SortOrder(Enum):
    """排序方向"""
    ASCENDING = "asc"      # 升序
    DESCENDING = "desc"    # 降序

def scan_files(
    directory: typing.Union[str, pathlib.Path],
    extensions: typing.Optional[typing.Iterable[str]] = None,
    recursive: bool = False,
    absolute_path: bool = True,
    include_suffix: bool = True,
    sort_by: typing.Optional[SortKey] = None,
    sort_order: SortOrder = SortOrder.ASCENDING,
    case_sensitive: bool = True
) -> typing.List[str]:
    """扫描目录中的文件，支持灵活配置
    
    Args:
        directory: 要扫描的目录路径
        extensions: 需要匹配的文件扩展名列表，如 ['.jpg', '.png']。默认为 None 表示所有文件
        recursive: 是否递归扫描子目录
        absolute_path: 是否返回绝对路径
        include_suffix: 是否包含文件后缀名
        sort_by: 排序依据，可选值为 SortKey 枚举成员。默认为 None 表示不排序
        sort_order: 排序方向，可选 SortOrder.ASCENDING 或 SortOrder.DESCENDING
        case_sensitive: 排序时是否区分大小写（仅对名称排序有效）
        
    Returns:
        符合条件的文件列表
    """
    # 标准化目录路径
    dir_path = pathlib.Path(directory)
    
    # 处理扩展名参数
    if extensions is not None:
        # 确保扩展名以点开头
        normalized_extensions = {ext.lower() if ext.startswith('.') else f'.{ext}' 
                                for ext in extensions}
    else:
        normalized_extensions = None
    
    # 构建路径生成器
    if recursive:
        paths = dir_path.rglob('*')
    else:
        paths = dir_path.iterdir()
    
    # 过滤文件
    files = [path for path in paths if path.is_file()]
    
    # 筛选扩展名
    if normalized_extensions is not None:
        files = [f for f in files if f.suffix.lower() in normalized_extensions]
    
    # 排序
    if sort_by is not None:
        reverse = (sort_order == SortOrder.DESCENDING)
        
        if sort_by == SortKey.NAME:
            files.sort(key=lambda f: f.name, reverse=reverse)
            if not case_sensitive:
                files.sort(key=lambda f: f.name.lower(), reverse=reverse)
                
        elif sort_by == SortKey.STEM:
            files.sort(key=lambda f: f.stem, reverse=reverse)
            if not case_sensitive:
                files.sort(key=lambda f: f.stem.lower(), reverse=reverse)
                
        elif sort_by == SortKey.SIZE:
            files.sort(key=lambda f: f.stat().st_size, reverse=reverse)
            
        elif sort_by == SortKey.MODIFIED_TIME:
            files.sort(key=lambda f: f.stat().st_mtime, reverse=reverse)
            
        elif sort_by == SortKey.CREATION_TIME:
            files.sort(key=lambda f: f.stat().st_ctime, reverse=reverse)
    
    # 格式化结果
    result = []
    for path in files:
        # 处理文件名（是否包含后缀）
        if include_suffix:
            name_part = path.name
        else:
            name_part = path.stem
            
        # 处理路径（绝对路径或相对路径）
        if absolute_path:
            full_path = str(path.parent.resolve() / name_part)
        else:
            full_path = str(path.parent / name_part)
            
        result.append(full_path)
    
    return result


def Scanfile_Picture_Name(file_path: str) -> list:
    """扫描路径下所有的图片文件名(仅包含文件名和后缀)

    Args:
        file_path (str): 需要扫描的目录路径

    Returns:
        list: 图片文件名列表，格式为 "文件名.后缀"

    Examples:
        >>> Scanfile_Picture_Name("/home/user/images")
        ['photo.jpg', 'background.png']
    """
    return scan_files(
        file_path, 
        extensions=['.jpg', '.png', '.webp', '.jpeg'],
        absolute_path=False, 
        include_suffix=True
    )


def Scanfile_Picture_AbsolutePath(file_path: str) -> list:
    """扫描路径下所有图片文件的绝对路径(包含后缀)

    Args:
        file_path (str): 需要扫描的目录路径

    Returns:
        list: 图片文件的绝对路径列表

    Examples:
        >>> Scanfile_Picture_AbsolutePath("/home/user/images")
        ['/home/user/images/photo.jpg', '/home/user/images/subdir/image.webp']
    """
    return scan_files(
        file_path, 
        extensions=['.jpg', '.png', '.webp', '.jpeg'],
        absolute_path=True, 
        include_suffix=True
    )


def Scanfile_Picture_WithoutSuffix(file_path: str) -> list:
    """扫描路径下所有图片文件的名称(不包含后缀)

    Args:
        file_path (str): 需要扫描的目录路径

    Returns:
        list: 图片文件名列表(不含后缀)

    Examples:
        >>> Scanfile_Picture_WithoutSuffix("/home/user/images")
        ['photo', 'background']
    """
    return scan_files(
        file_path, 
        extensions=['.jpg', '.png', '.webp', '.jpeg'],
        absolute_path=False, 
        include_suffix=False
    )





def BackupFile(_source_file: typing.Union[str, typing.List[str]], _target_dir: typing.Union[str, typing.List[str]]) -> typing.Union[bool, int]:
    """备份单个或多个文件到指定目录或多个目录
    
    该函数支持两种调用方式：
    1. 传入单个源文件路径和单个目标目录路径 此时返回布尔值表示操作是否成功
    2. 传入源文件路径列表和目标目录路径列表 此时返回成功复制的文件数量
    
    Args:
        _source_file: 源文件路径(相对或绝对)或源文件路径列表
        _target_dir: 目标目录路径(相对或绝对)或目标目录路径列表
    
    Returns:
        当传入单个路径时 返回布尔值 成功为True 失败为False
        当传入列表时 返回整数 表示成功复制的文件数量
    
    Raises:
        FileNotFoundError: 当源文件不存在时抛出
    
    Examples:
        # 单个文件备份
        success = BackupFile("data/file.txt", "backup/")
        
        # 批量备份
        files = ["file1.txt", "file2.txt"]
        dirs = ["backup1/", "backup2/"]
        count = BackupFile(files, dirs)  # 会执行4次复制操作
    """
    # 处理单个文件备份的情况
    if isinstance(_source_file, str) and isinstance(_target_dir, str):
        # 确保源文件存在
        if not os.path.exists(_source_file):
            raise FileNotFoundError(f"源文件不存在: {_source_file}")
        
        # 确保目标目录存在
        if not os.path.exists(_target_dir):
            os.makedirs(_target_dir, exist_ok=True)
        
        # 构建目标文件路径
        file_name = os.path.basename(_source_file)
        target_file = os.path.join(_target_dir, file_name)
        
        # 执行复制操作
        try:
            shutil.copy2(_source_file, target_file)
            result = True
        except Exception:
            result = False
        
        return result
    
    # 处理批量备份的情况
    elif isinstance(_source_file, list) and isinstance(_target_dir, list):
        success_count = 0
        
        # 遍历所有源文件和目标目录的组合
        for source_file in _source_file:
            for target_dir in _target_dir:
                try:
                    # 递归调用单个文件备份函数
                    success = BackupFile(source_file, target_dir)
                    if success:
                        success_count += 1
                except FileNotFoundError:
                    # 忽略不存在的文件 继续处理其他文件
                    continue
        
        return success_count
    
    # 不支持的参数类型组合
    else:
        raise TypeError("参数类型组合不支持 请传入两个字符串或两个列表")


files = scan_files("C:/Users/29524/Desktop/online-shop_-selenium-library", extensions=['.jpg', '.png', '.webp', '.jpeg'], absolute_path=True, include_suffix=True,sort_by=SortOrder.ASCENDING,recursive=True)
